home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 11 / CU Amiga Magazine's Super CD-ROM 11 (1997)(EMAP Images)(GB)(Track 1 of 3)[!][issue 1997-06].iso / cucd / graphics / mpimage / si / ilbmw.c < prev    next >
C/C++ Source or Header  |  1996-12-01  |  7KB  |  219 lines

  1. /*----------------------------------------------------------------------*
  2.  * ILBMW.C  Support routines for writing ILBM files using IFFParse.
  3.  * (IFF is Interchange Format File.)
  4.  *
  5.  * Based on code by Jerry Morrison and Steve Shaw, Electronic Arts.
  6.  * This software is in the public domain.
  7.  *
  8.  * This version for the Commodore-Amiga computer.
  9.  *
  10.  * mod 06-Apr-92 - Add JM change for separate source and dest modulo
  11.  * 39.5 (11/92) - in putbody, changed bufsize check to compare against
  12.  *                FileRowBytes (amount being written), not rowBytes
  13.  *----------------------------------------------------------------------*/
  14. #define INTUI_V36_NAMES_ONLY
  15.  
  16. #include "iffp/ilbm.h"
  17. #include "iffp/packer.h"
  18.  
  19. #include <graphics/gfxbase.h>
  20.  
  21. //extern struct Library *GfxBase;
  22.  
  23. /*---------- initbmhd -------------------------------------------------*/
  24. long initbmhd(BitMapHeader *bmhd, struct BitMap *bitmap,
  25.           WORD masking, WORD compression, WORD transparentColor,
  26.           WORD width, WORD height, WORD pageWidth, WORD pageHeight,
  27.           ULONG modeid)
  28.     {
  29. //    extern struct Library *GfxBase;
  30.     struct DisplayInfo DI;
  31.  
  32.     D(bug("In InitBMHD\n"));
  33.  
  34.     if((!bmhd)||(!bitmap)||(!width)||(!height))
  35.     return(CLIENT_ERROR);
  36.  
  37.     bmhd->w = width;
  38.     bmhd->h = height;
  39.     bmhd->x = bmhd->y = 0;    /* Default position is (0,0).*/
  40.     bmhd->nPlanes = bitmap->Depth;
  41.     bmhd->masking = masking;
  42.     bmhd->compression = compression;
  43.     bmhd->flags = BMHDF_CMAPOK;    /* we will store 8 significant bits */
  44.     bmhd->transparentColor = transparentColor;
  45.     bmhd->pageWidth = pageWidth;
  46.     bmhd->pageHeight = pageHeight;
  47.  
  48.     bmhd->xAspect = 0;    /* So we can tell when we've got it */
  49.     if(GfxBase->LibNode.lib_Version >=36)
  50.     {
  51.        if(GetDisplayInfoData(NULL, (UBYTE *)&DI,
  52.         sizeof(struct DisplayInfo), DTAG_DISP, modeid))
  53.         {
  54.             bmhd->xAspect =  DI.Resolution.x;
  55.             bmhd->yAspect =  DI.Resolution.y;
  56.         }
  57.     }
  58.  
  59.     /* If running under 1.3 or GetDisplayInfoData failed, use old method
  60.      * of guessing aspect ratio
  61.      */
  62.     if(! bmhd->xAspect)
  63.     {
  64.         bmhd->xAspect =  44;
  65.         bmhd->yAspect =
  66.         ((struct GfxBase *)GfxBase)->DisplayFlags & PAL ? 44 : 52;
  67.         if(modeid & HIRES)    bmhd->xAspect = bmhd->xAspect >> 1;
  68.         if(modeid & LACE)    bmhd->yAspect = bmhd->yAspect >> 1;
  69.     }
  70.  
  71.     return( IFF_OKAY );
  72.     }
  73.  
  74. /*---------- putcmap ---------------------------------------------------*/
  75. /* This function will accept a table of color values in one of the
  76.  * following forms:
  77.  *  if bitspergun=4,  colortable is words, each with nibbles 0RGB
  78.  *  if bitspergun=8,  colortable is bytes of RGBRGB etc. (like a CMAP)
  79.  *  if bitspergun=32, colortable is ULONGS of RGBRGB etc.
  80.  *     (only the high eight bits of each gun will be written to CMAP)
  81.  */
  82. long putcmap(struct IFFHandle *iff, APTR colortable,
  83.          UWORD ncolors, UWORD bitspergun)
  84.    {
  85.    long error, offs;
  86.    WORD  *tabw;
  87.    UBYTE *tab8;
  88.    ColorRegister cmapReg;
  89.  
  90.    D(bug("In PutCMAP\n"));
  91.  
  92.    if((!iff)||(!colortable))    return(CLIENT_ERROR);
  93.  
  94.    /* size of CMAP is 3 bytes * ncolors */
  95.    if(error = PushChunk(iff, NULL, ID_CMAP, ncolors * sizeofColorRegister))
  96.     return(error);
  97.  
  98.    D(bug("Pushed ID_CMAP, error = %ld\n",error));
  99.  
  100.    if(bitspergun == 4)
  101.     {
  102.        /* Store each 4-bit value n as nn */
  103.     tabw = (UWORD *)colortable;
  104.        for( ;  ncolors;  --ncolors )
  105.         {
  106.               cmapReg.red    = ( *tabw >> 4 ) & 0xf0;
  107.               cmapReg.red   |= (cmapReg.red >> 4);
  108.  
  109.               cmapReg.green  = ( *tabw      ) & 0xf0;
  110.               cmapReg.green |= (cmapReg.green >> 4);
  111.  
  112.               cmapReg.blue   = ( *tabw << 4 ) & 0xf0;
  113.               cmapReg.blue  |= (cmapReg.blue >> 4);
  114.  
  115.               if((WriteChunkBytes(iff, (BYTE *)&cmapReg, sizeofColorRegister))
  116.                 != sizeofColorRegister)
  117.                         return(IFFERR_WRITE);
  118.               ++tabw;
  119.               }
  120.     }
  121.    else if((bitspergun == 8)||(bitspergun == 32))
  122.     {
  123.     tab8 = (UBYTE *)colortable;
  124.     offs = (bitspergun == 8) ? 1 : 4;
  125.        for( ;  ncolors;  --ncolors )
  126.         {
  127.         cmapReg.red   = *tab8;
  128.         tab8 += offs;
  129.         cmapReg.green = *tab8;
  130.         tab8 += offs;
  131.         cmapReg.blue  = *tab8;
  132.         tab8 += offs;
  133.               if((WriteChunkBytes(iff, (BYTE *)&cmapReg, sizeofColorRegister))
  134.                 != sizeofColorRegister)
  135.                         return(IFFERR_WRITE);
  136.         }
  137.     }
  138.    else (error = CLIENT_ERROR);
  139.  
  140.    D(bug("Wrote registers, error = %ld\n",error));
  141.  
  142.    error = PopChunk(iff);
  143.    return(error);
  144.    }
  145.  
  146. /*---------- putbody ---------------------------------------------------*/
  147. /* NOTE: This implementation could be a LOT faster if it used more of the
  148.  * supplied buffer. It would make far fewer calls to IFFWriteBytes (and
  149.  * therefore to DOS Write).
  150.  *
  151.  * Incorporates modification by Jesper Steen Moller to accept source
  152.  * rows wider than dest rows, with one modulo variable for source bitplane
  153.  * rows and one for the ILBM bitmap rows.
  154.  */
  155. long putbody(struct IFFHandle *iff, struct BitMap *bitmap, BYTE *mask,
  156.          BitMapHeader *bmhd, BYTE *buffer, LONG bufsize)
  157.    {
  158.    long error;
  159.    LONG rowBytes = bitmap->BytesPerRow;       /* for source modulo only */
  160.    LONG FileRowBytes = RowBytes(bmhd->w);  /* width to write in bytes */
  161.    int dstDepth = bmhd->nPlanes;
  162.    UBYTE compression = bmhd->compression;
  163.    int planeCnt;        /* number of bit planes including mask */
  164.    register int iPlane, iRow;
  165.    register LONG packedRowBytes;
  166.    BYTE *buf;
  167.    BYTE *planes[MAXSAVEDEPTH + 1]; /* array of ptrs to planes & mask */
  168.  
  169.    D(bug("In PutBODY, rows = %ld, rowBytes = %ld, expected %ld\n", bitmap->Rows, rowBytes, RowBytes(bmhd->w)));
  170.  
  171.    if ( bufsize < MaxPackedSize(FileRowBytes)  || /* Must buffer a comprsd row*/
  172.         compression > cmpByteRun1  ||          /* bad arg */
  173.     bitmap->Rows != bmhd->h   ||          /* inconsistent */
  174.     rowBytes < FileRowBytes  ||              /* inconsistent*/
  175.     bitmap->Depth < dstDepth   ||          /* inconsistent */
  176.     dstDepth > MAXSAVEDEPTH )          /* too many for this routine*/
  177.         return(CLIENT_ERROR);
  178.  
  179.    planeCnt = dstDepth + (mask == NULL ? 0 : 1);
  180.  
  181.    /* Copy the ptrs to bit & mask planes into local array "planes" */
  182.    for (iPlane = 0; iPlane < dstDepth; iPlane++)
  183.       planes[iPlane] = (BYTE *)bitmap->Planes[iPlane];
  184.    if (mask != NULL)
  185.       planes[dstDepth] = mask;
  186.  
  187.    /* Write out a BODY chunk header */
  188.    if(error = PushChunk(iff, NULL, ID_BODY, IFFSIZE_UNKNOWN)) return(error);
  189.  
  190.    /* Write out the BODY contents */
  191.    for (iRow = bmhd->h; iRow > 0; iRow--)  {
  192.       for (iPlane = 0; iPlane < planeCnt; iPlane++)  {
  193.  
  194.          /* Write next row.*/
  195.          if (compression == cmpNone) {
  196.         if(WriteChunkBytes(iff,planes[iPlane],FileRowBytes) != FileRowBytes)
  197.         error = IFFERR_WRITE;
  198.             planes[iPlane] += rowBytes; /* Possibly skipping unused bytes */
  199.             }
  200.  
  201.          /* Compress and write next row.*/
  202.          else {
  203.             buf = buffer;
  204.             packedRowBytes = packrow(&planes[iPlane], &buf, FileRowBytes);
  205.         /* Note that packrow incremented planes already by FileRowBytes */
  206.             planes[iPlane] += rowBytes-FileRowBytes; /* Possibly skipping unused bytes */
  207.         if(WriteChunkBytes(iff,buffer,packedRowBytes) != packedRowBytes)
  208.         error = IFFERR_WRITE;
  209.             }
  210.  
  211.          if(error)    return(error);
  212.          }
  213.       }
  214.  
  215.    /* Finish the chunk */
  216.    error = PopChunk(iff);
  217.    return(error);
  218.    }
  219.